package com.misty.blog.controller.blogController;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.misty.auth.component.LoginUser;
import com.misty.blog.annotation.ViewStatistics;
import com.misty.blog.bean.param.blog.*;
import com.misty.blog.bean.vo.blog.BlogVo;
import com.misty.blog.service.*;
import com.misty.common.Util.RedisCache;
import com.misty.common.Util.SecurityUtil;
import com.misty.common.bean.Result;
import com.misty.common.constants.RedisKey;
import com.misty.common.constants.ResultEnum;
import com.misty.dao.domain.Blog;
import com.misty.dao.domain.BlogTag;
import com.misty.dao.domain.Users;
import com.misty.dao.dto.BlogDto;
import com.misty.dao.vo.BlogTagVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/fore/blog")
@Slf4j
public class BlogController {

    @Autowired
    private BlogService blogService;

    @Autowired
    private UsersService usersService;
    @Autowired
    private ConcernListService concernListService;

    @Autowired
    private TagService tagService;

    @Autowired
    private BlogTagService blogTagService;

    @Autowired
    private BlogLikesService blogLikesService;

    @Autowired
    private BlogCollectionService blogCollectionService;

    @Autowired
    private RedisCache redisCache;



    @GetMapping()
    public Result<?> page(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(defaultValue = "") String search,
            @RequestParam(defaultValue = "") String tag,
            @RequestParam(defaultValue = "") String type
    ) {
        return blogService.page(pageNum,pageSize,search,tag,type);
    }

    @GetMapping("/order")
    public Result<?> order(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(defaultValue = "") String search
    ) {
        return blogService.order(pageNum,pageSize,search);
    }


    @GetMapping("/selectBATByUser")
    public Result<?> selectBlogAndTagByUser(BATParam param){
//        Result<List<String>> listResult = tagService.selectTagNameByUser(param.getUserId());
//        if(listResult.isSuccesResult()){
//            return blogService.selectBlogAndTagByUser(param);
//        }
        Page<BlogTagVo> blogTagVoPage = new Page<>();

        //查询用户下所有博客
        Result<Page<Blog>> pageResult = blogService
                .selectPageByUserId(param.getPageNum(), param.getPageSize(), param.getUserId());
        if(pageResult.isErrorResult()){
            return Result.error("根据该用户分页获取博客失败!");
        }
        //page数据转换
        Page<Blog> page = pageResult.getData();
        IPage<BlogTagVo> convertPage = page.convert(u -> {
            BlogTagVo v = new BlogTagVo();
            BeanUtil.copyProperties(u, v);
            return v;
        });

        List<BlogTagVo> records = convertPage.getRecords();
        //循环
        for (BlogTagVo blog : records) {

            Result<List<String>> listResult = tagService.selectTagNameByBlog(blog.getId());
            //假如有标签
            if(listResult.isSuccesResult()) {
                blog.setTagList(listResult.getData());
            }
        }

        return Result.success("根据该用户分页获取博客成功!",convertPage);
    }


    @GetMapping("/{id}")
    @ViewStatistics
    public Result<?> selectByIdWithUser(@PathVariable(name = "id") Integer id ){
        if(redisCache.exists(RedisKey.BLOG_DETAIL + id)){
            BlogVo cacheVo = (BlogVo)redisCache.getCacheObject(RedisKey.BLOG_DETAIL + id);
            return Result.success("查询对应博客和用户成功！",cacheVo);
        }
        //获取博客信息
        Result<?> result = blogService.selectByIdWithUser(id);
        if(result.isErrorResult()) {
            return result;
        }
//        获取博客标签信息
        BlogDto blogDto = (BlogDto) result.getData();
        Result<?> tagResult = tagService.selectTagNameByBlog(blogDto.getId());
        BlogVo blogVo = new BlogVo();
        BeanUtil.copyProperties(blogDto,blogVo);
        if(tagResult.isSuccesResult()){
            List<String> tagList = (List<String>) tagResult.getData();
            blogVo.setTagList(tagList);
        }

        //判断登录

        Authentication authentication = SecurityUtil.getAuthentication();

        if(authentication != null && !(authentication instanceof AnonymousAuthenticationToken)){
            //判断点赞、收藏
            Integer currentUserId = ((LoginUser)authentication.getPrincipal()).getUser().getId();
            Integer blogId = blogDto.getId();
            Boolean ifLike = blogLikesService.judgeIfLike(blogId,currentUserId);
            Boolean ifColCount = blogCollectionService.judgeIfCollection(blogId,currentUserId);
            Boolean concernType = concernListService.isConcern(blogId,currentUserId,null);
            blogVo.setLikeBoolean(ifLike);
            blogVo.setCollectionBoolean(ifColCount);
            blogVo.setConcernType(concernType);
        }else {
            blogVo.setLikeBoolean(false);
            blogVo.setCollectionBoolean(false);
        }

        redisCache.setCacheObject(RedisKey.BLOG_DETAIL + id,blogVo,60, TimeUnit.MINUTES);

        return Result.success("查询对应博客和用户成功！",blogVo);
    }


//    @PutMapping("blog/update")
//    public Result<?> update(@RequestBody  Blog  blog) {
//         blogMapper.updateById(blog);
//        return Result.success();
//    }

//    @DeleteMapping("blog/delete")
//    public Result<?> delete(@RequestParam(name = "id") Integer  blogId) {
//         blogMapper.deleteById( blogId);
//        return Result.success();
//    }


    @PreAuthorize("hasAuthority('fore/blog')")
    @PostMapping("publish")
    @Transactional(transactionManager = "mistyTransactionManager")
    public Result save(@RequestBody SaveParam param, HttpServletRequest request) {

        //更新
        if(param.getId() != null){
            Result result = blogService.updateBlog(param,request);
            return result;
        }

        /*          新增           */
        //确保该博客存在对应用户
        Users users = new Users();
        users.setUsername(param.getUsername());
        Users oneUser = usersService.selectOne(users);
        if(ObjectUtil.isEmpty(oneUser)){
            return Result.error(400,"发布失败！");
        }

        //保存该用户博客
        param.setUserId(oneUser.getId());
        Blog blogEntity = new Blog();
        blogEntity.setViews(0);
        BeanUtil.copyProperties(param,blogEntity);
        int insert = blogService.saveBlog(blogEntity);
        if( insert == 0){
            return Result.error("发布失败！");
        }

        //保存标签
        Result<?> result = tagService.addAllTag(param.getTagList(), blogEntity.getId());
        if(result.isErrorResult()){
            return Result.error("发布失败！");
        }
        return Result.success("发布成功！");
    }

    @GetMapping("/fetchSuggest")
    public Result<?> fetchSuggest(FetchSuggestParam param){
        return blogService.fetchSuggest(param);
    }

    @PutMapping("/likeCountChange")
    @PreAuthorize("hasAuthority('fore/blog')")
    public Result<?> likeCountChange(@RequestBody LikeCountParam param){

        redisCache.deleteObject(RedisKey.BLOG_DETAIL + param.getBlogId());

        //判断登录
        Authentication authentication = SecurityUtil.getAuthentication();
        if((authentication instanceof AnonymousAuthenticationToken)){
            return Result.error(ResultEnum.UN_LOGIN.getValue(),"用户未登录！");
        }
        Integer currentUserId = ((LoginUser)authentication.getPrincipal()).getUser().getId();

        //判断是否已经点赞过了
        Boolean ifLike = blogLikesService.judgeIfLike(param.getBlogId(),currentUserId);
        Blog blogOne = blogService.getById(param.getBlogId());

//        UpdateWrapper<BlogLikes> updateWrapper;
        Result<?> result;
        //假如点赞过了，则取消点赞
        if(ifLike){
            //本博客点赞数减1
            param.setCount(blogOne.getLikesCount()-1);
            result = blogService.likeCountChange(param,currentUserId);
            if(result.getCode() != 0) {
                return result;
            }
            //删除对应点赞记录
            return blogLikesService.cancelLike(param,currentUserId);
        }
        //否则，添加点赞记录
        //本博客点赞数加1
        param.setCount(blogOne.getLikesCount()+1);
        result = blogService.likeCountChange(param,currentUserId);
        if(result.getCode() != 0) {
            return result;
        }
        //增加对应点赞记录
        return blogLikesService.addLike(param,currentUserId);

    }

    @PutMapping("/colCountChange")
    @PreAuthorize("hasAuthority('fore/blog')")
    public Result<?> colCountChange(@RequestBody ColCountParam param){

        redisCache.deleteObject(RedisKey.BLOG_DETAIL + param.getBlogId());

        //判断登录
        Authentication authentication = SecurityUtil.getAuthentication();
        if((authentication instanceof AnonymousAuthenticationToken)){
            return Result.error(ResultEnum.UN_LOGIN.getValue(),"用户未登录！");
        }
        Integer currentUserId = ((LoginUser)authentication.getPrincipal()).getUser().getId();


        //判断是否已经收藏过了
        Boolean ifColCount = blogCollectionService.judgeIfCollection(param.getBlogId(),currentUserId);
        Blog blogOne = blogService.getById(param.getBlogId());

//        UpdateWrapper<BlogLikes> updateWrapper;
        Result<?> result;
        //假如收藏过了，则取消收藏
        if(ifColCount){
            //本博客收藏数减1
            param.setCount(blogOne.getCollectionCount()-1);
            result = blogService.colCountChange(param,currentUserId);
            if(result.getCode() != 0) {
                return result;
            }
            //删除对应收藏记录
            return blogCollectionService.cancelCollection(param,currentUserId);
        }
        //否则，添加收藏记录
        //本博客点赞数加1
        param.setCount(blogOne.getCollectionCount()+1);
        result = blogService.colCountChange(param,currentUserId);
        if(result.getCode() != 0) {
            return result;
        }
        //增加对应收藏记录
        return blogCollectionService.addCollection(param,currentUserId);
    }

    @DeleteMapping("/delete")
    @PreAuthorize("hasAuthority('fore/blog')")
    @Transactional(transactionManager = "mistyTransactionManager")
    public Result<?> delete(DelParam param) {

        redisCache.deleteObject(RedisKey.BLOG_DETAIL + param.getBlogId());

        //删除博客
        boolean delBlog = blogService.removeById(param.getBlogId());
        if(!delBlog){
            return Result.error("删除博客失败!");
        }
        //删除对应标签
        UpdateWrapper<BlogTag> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(BlogTag::getBlogId,param.getBlogId());
        boolean remove = blogTagService.remove(updateWrapper);
        if(!remove){
            return Result.error("删除博客失败!");
        }
        return Result.success("删除博客成功!");
    }
}
